/**
 * 数据库类型映射模块
 * 
 * 提供将不同数据库类型映射到TypeScript类型的功能
 * 支持MySQL、PostgreSQL、Oracle、SQL Server等多种数据库
 * 
 * @module dbTypeMapping
 */

/**
 * 默认类型映射配置
 * @type {Object}
 */
const DEFAULT_TYPE_MAPPINGS = {
    // MySQL类型映射
    mysql: {
        // 数值类型
        'tinyint': (column) => column.columnType?.toLowerCase().includes('(1)') ? 'boolean' : 'number',
        'smallint': 'number',
        'mediumint': 'number',
        'int': 'number',
        'integer': 'number',
        'bigint': (column) => column.numericPrecision > 15 ? 'string' : 'number',
        'float': 'number',
        'double': 'number',
        'decimal': 'number',
        'numeric': 'number',

        // 字符串类型
        'char': 'string',
        'varchar': 'string',
        'tinytext': 'string',
        'text': 'string',
        'mediumtext': 'string',
        'longtext': 'string',

        // 日期和时间类型
        'date': 'string',
        'time': 'string',
        'year': 'string',
        'datetime': 'string',
        'timestamp': 'string',

        // 二进制类型
        'binary': 'string',
        'varbinary': 'string',
        'tinyblob': 'string',
        'blob': 'string',
        'mediumblob': 'string',
        'longblob': 'string',

        // 枚举和集合类型
        'enum': (column) => {
            // 从column_type提取枚举值，如"enum('value1','value2')"
            const matches = column.columnType?.match(/'([^']*)'/g) || [];
            return matches.length > 0
                ? matches.map(m => `'${m.replace(/'/g, '')}'`).join(' | ')
                : 'string';
        },
        'set': 'string',

        // JSON类型
        'json': 'any',

        // 空间数据类型
        'geometry': 'any',
        'point': 'any',
        'linestring': 'any',
        'polygon': 'any',
        'multipoint': 'any',
        'multilinestring': 'any',
        'multipolygon': 'any',
        'geometrycollection': 'any'
    },

    // PostgreSQL类型映射
    postgresql: {
        // 数值类型
        'smallint': 'number',
        'integer': 'number',
        'bigint': (column) => column.numericPrecision > 15 ? 'string' : 'number',
        'decimal': 'number',
        'numeric': 'number',
        'real': 'number',
        'double precision': 'number',
        'serial': 'number',
        'bigserial': (column) => column.numericPrecision > 15 ? 'string' : 'number',

        // 货币类型
        'money': 'string',

        // 字符类型
        'character': 'string',
        'char': 'string',
        'character varying': 'string',
        'varchar': 'string',
        'text': 'string',

        // 二进制类型
        'bytea': 'string',

        // 日期/时间类型
        'timestamp': 'string',
        'date': 'string',
        'time': 'string',
        'interval': 'string',

        // 布尔类型
        'boolean': 'boolean',

        // 枚举类型
        'enum': 'string',

        // 几何类型
        'point': 'any',
        'line': 'any',
        'lseg': 'any',
        'box': 'any',
        'path': 'any',
        'polygon': 'any',
        'circle': 'any',

        // 网络地址类型
        'cidr': 'string',
        'inet': 'string',
        'macaddr': 'string',

        // JSON类型
        'json': 'any',
        'jsonb': 'any',

        // 数组类型
        'array': 'any[]',

        // UUID类型
        'uuid': 'string',

        // XML类型
        'xml': 'string'
    },

    // Oracle类型映射
    oracle: {
        // 数值类型
        'number': (column) => {
            // 如果scale为0且precision较小，则为整数
            if (column.numericScale === 0 && column.numericPrecision <= 10) {
                return 'number';
            }
            // 如果precision很大，用字符串表示
            if (column.numericPrecision > 15) {
                return 'string';
            }
            return 'number';
        },
        'float': 'number',
        'binary_float': 'number',
        'binary_double': 'number',

        // 字符类型
        'char': 'string',
        'varchar2': 'string',
        'nchar': 'string',
        'nvarchar2': 'string',
        'clob': 'string',
        'nclob': 'string',
        'long': 'string',

        // 日期和时间类型
        'date': 'string',
        'timestamp': 'string',
        'timestamp with time zone': 'string',
        'timestamp with local time zone': 'string',
        'interval year to month': 'string',
        'interval day to second': 'string',

        // 二进制类型
        'raw': 'string',
        'long raw': 'string',
        'blob': 'string',
        'bfile': 'string',

        // 行ID类型
        'rowid': 'string',
        'urowid': 'string',

        // XML类型
        'xmltype': 'string'
    },

    // SQL Server类型映射
    sqlserver: {
        // 精确数值
        'bit': 'boolean',
        'tinyint': 'number',
        'smallint': 'number',
        'int': 'number',
        'bigint': (column) => column.numericPrecision > 15 ? 'string' : 'number',
        'decimal': 'number',
        'numeric': 'number',
        'smallmoney': 'number',
        'money': 'number',

        // 近似数值
        'float': 'number',
        'real': 'number',

        // 日期和时间
        'date': 'string',
        'time': 'string',
        'datetime': 'string',
        'datetime2': 'string',
        'smalldatetime': 'string',
        'datetimeoffset': 'string',

        // 字符串
        'char': 'string',
        'varchar': 'string',
        'text': 'string',
        'nchar': 'string',
        'nvarchar': 'string',
        'ntext': 'string',

        // 二进制
        'binary': 'string',
        'varbinary': 'string',
        'image': 'string',

        // 其他类型
        'uniqueidentifier': 'string',
        'xml': 'string',
        'sql_variant': 'any',
        'hierarchyid': 'string',
        'geometry': 'any',
        'geography': 'any'
    }
};

/**
 * 数据库引擎类型
 * @typedef {'mysql'|'postgresql'|'oracle'|'sqlserver'} DbEngine
 */

/**
 * 将数据库类型映射为TypeScript类型
 * 
 * @param {string} dbType - 数据库字段类型
 * @param {Object} column - 列属性对象
 * @param {DbEngine} dbEngine - 数据库引擎类型
 * @param {Object} customMappings - 自定义类型映射
 * @returns {string} TypeScript类型
 */
function mapToTsType(dbType, column, dbEngine = 'mysql', customMappings = {}) {
    // 默认值处理
    if (!dbType) return 'any';

    // 获取类型映射
    const engineMappings = {
        ...DEFAULT_TYPE_MAPPINGS[dbEngine.toLowerCase()],
        ...customMappings
    };

    // 如果没有找到对应的引擎映射，使用mysql作为默认
    if (!engineMappings) {
        return mapToTsType(dbType, column, 'mysql', customMappings);
    }

    // 标准化类型名称
    const normalizedType = dbType.toLowerCase().trim();

    // 提取基本类型，移除长度信息，如varchar(255) -> varchar
    const baseType = normalizedType.replace(/\(.*\)/, '').trim();

    // 查找映射
    const typeMapping = engineMappings[baseType];

    // 空值处理
    const nullableSuffix = column.isNullable === 'YES' ? ' | null' : '';

    // 应用映射
    if (typeMapping) {
        if (typeof typeMapping === 'function') {
            return `${typeMapping(column)}${nullableSuffix}`;
        }
        return `${typeMapping}${nullableSuffix}`;
    }

    // 未知类型默认为any
    console.warn(`未知的数据库类型: ${dbType}，使用默认类型'any'`);
    return `any${nullableSuffix}`;
}

/**
 * 根据数据库类型生成TypeScript类型注释
 * 
 * @param {string} dbType - 数据库字段类型
 * @param {Object} column - 列属性对象
 * @param {DbEngine} dbEngine - 数据库引擎类型
 * @returns {string} TypeScript类型注释
 */
function generateTypeComment(dbType, column, dbEngine = 'mysql') {
    if (!dbType) return '';

    // 通用注释
    let comment = `@db {${dbType}}`;

    // 添加主键信息
    if (column.isPrimaryKey === 'YES') {
        comment += ' @primaryKey';
    }

    // 添加外键信息
    if (column.referencedTable && column.referencedColumn) {
        comment += ` @foreignKey {${column.referencedTable}.${column.referencedColumn}}`;
    }

    // 添加是否自增信息
    if (column.isAutoIncrement === 'YES') {
        comment += ' @autoIncrement';
    }

    // 添加默认值信息
    if (column.defaultValue) {
        comment += ` @default {${column.defaultValue}}`;
    }

    return comment;
}

/**
 * 验证类型映射配置
 * 
 * @param {Object} mappingConfig - 类型映射配置
 * @returns {Object} 验证结果
 */
function validateMappingConfig(mappingConfig) {
    const errors = [];
    const warnings = [];

    // 检查引擎配置
    for (const engine in mappingConfig) {
        if (!DEFAULT_TYPE_MAPPINGS[engine]) {
            warnings.push(`未知的数据库引擎: ${engine}`);
        }

        // 检查每个类型映射
        const mappings = mappingConfig[engine];
        for (const dbType in mappings) {
            const mapping = mappings[dbType];

            if (typeof mapping !== 'string' && typeof mapping !== 'function') {
                errors.push(`无效的类型映射 [${engine}.${dbType}]: 应为字符串或函数`);
            }
        }
    }

    return {
        valid: errors.length === 0,
        errors,
        warnings
    };
}

/**
 * 加载自定义类型映射
 * 
 * @param {string} configPath - 配置文件路径
 * @returns {Object} 自定义类型映射
 */
function loadCustomMappings(configPath) {
    try {
        // 检查文件是否存在
        const fs = require('fs');
        if (!fs.existsSync(configPath)) {
            console.warn(`自定义类型映射文件不存在: ${configPath}`);
            return {};
        }

        // 加载配置文件
        const customMappings = require(configPath);

        // 验证配置
        const validation = validateMappingConfig(customMappings);
        if (!validation.valid) {
            console.error('自定义类型映射配置无效:');
            validation.errors.forEach(err => console.error(`- ${err}`));
            return {};
        }

        // 输出警告
        if (validation.warnings.length > 0) {
            console.warn('自定义类型映射配置警告:');
            validation.warnings.forEach(warn => console.warn(`- ${warn}`));
        }

        return customMappings;
    } catch (error) {
        console.error('加载自定义类型映射失败:', error);
        return {};
    }
}

// 导出模块
module.exports = {
    mapToTsType,
    generateTypeComment,
    loadCustomMappings,
    validateMappingConfig,
    DEFAULT_TYPE_MAPPINGS
}; 